package com.ruoyi.flow.common.tools.mediaconverter.converter;

import com.ruoyi.flow.common.tools.mediaconverter.converter.converter.ConverterFactory;
import com.ruoyi.flow.common.tools.mediaconverter.converter.converter.IConverter;
import com.google.common.base.Splitter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.List;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
 * 多媒体转换器主程序入口，用于将给定的多媒体文件转换为制定的目标类型。样例：
 * <pre>
 * MediaConverter converter = MediaConverter.builder().srcFilePath("D:/silk2mp3/wxid_y2prj0189ws122.silk").build();
 * MediaInfo mediaInfo = converter.decode();
 * </pre>
 * @author wtian
 *
 */
public class MediaConverter {
    private static final Logger LOGGER = LoggerFactory.getLogger(MediaConverter.class);
    /**
     * ffmpeg在Windows系统中的目录
     */
    protected String cmdDirOnWindows;
    /**
     * ffmpeg在Linux系统中的目录
     */
    protected String cmdDirOnLinux;
    /**
     * 目标文件路径
     */
    protected String destFilePath;

    protected long timeout;

    protected IConverter converter;

    protected MediaConverter(IConverter converter,Builder builder) {
        this.converter = converter;
        this.destFilePath = builder.destFilePath;
        this.cmdDirOnLinux = builder.cmdDirOnLinux;
        this.cmdDirOnWindows = builder.cmdDirOnWindows;
        this.timeout = builder.timeout;
    }

    public static Builder builder() {
        return new Builder();
    }

    /**
     * 构造类
     * @author Administrator
     *
     */
    public static class Builder {
        private static final String SUPPORTED_FORMAT = "mp3,silk,amr,aud,wmv,wav";
        /**
         * ffmpeg在Windows中的目录
         */
        private String cmdDirOnWindows = "D:/silk2mp3";
        /**
         * ffmpeg在Linux中的目录
         */
        private String cmdDirOnLinux;
        /**
         * 多媒体源文件路径
         */
        private String srcFilePath;
        /**
         * 多媒体转换后的存放路径
         */
        private String destDirPath;
        private String destFilePath;
        /**
         * 多媒体转换目标格式
         */
        private String format = "mp3";
        /**
         * 多媒体转换后的文件名
         */
        private String destFileName;

        /**
         * 超时时间
         */
        private long timeout = 30000;

        public Builder timeout(long timeout){
            checkState(timeout>0,"timeout must be greater than 0");
            this.timeout = timeout;
            return this;
        }

        /**
         * 设置ffmpeg文件在Windows中的安装目录
         * @param cmdDirOnWindows
         * @return
         */
        public Builder cmdDirOnWindows(String cmdDirOnWindows) {
            checkNotNull(cmdDirOnWindows);
            this.cmdDirOnWindows = cmdDirOnWindows;
            return this;
        }

        /**
         * 设置ffmpeg文件在Linux中的安装目录
         * @param cmdDirOnLinux
         * @return
         */
        public Builder cmdDirOnLinux(String cmdDirOnLinux) {
            checkNotNull(cmdDirOnLinux);
            this.cmdDirOnLinux = cmdDirOnLinux;
            return this;
        }

        /**
         * 设置多媒体源文件路径，必填
         * @param srcFilePath
         * @return
         */
        public Builder srcFilePath(String srcFilePath) {
            checkNotNull(srcFilePath);
            File srcFile = new File(srcFilePath);
            checkState(srcFile.exists(), "the file [{}] to be converted is not exist!", srcFilePath);
            this.srcFilePath = srcFile.getAbsolutePath();
            return this;
        }

        /**
         * 设置多媒体转换后的存放目录，默认与源文件同文件夹
         * @param destDirPath
         * @return
         */
        public Builder destDirPath(String destDirPath) {
            checkNotNull(destDirPath);
            File destDir = new File(destDirPath);
            if (!destDir.exists()) {
                destDir.mkdirs();
            }
            this.destDirPath = destDir.getAbsolutePath();
            return this;
        }

        /**
         * 设置多媒体转换后的文件名，默认与源文件同名
         * @param destFileName
         * @return
         */
        public Builder destFileName(String destFileName) {
            checkNotNull(destFileName);
            this.destFileName = destFileName;
            return this;
        }

        /**
         * 设置转换格式，默认mp3
         * @param format
         * @return
         */
        public Builder format(String format) {
            checkNotNull(format);
            checkState(checkFormatIsSupported(format), "unsupported format.the supported format are {}", SUPPORTED_FORMAT);
            this.format = format;
            return this;
        }

        public MediaConverter build() {
            checkNotNull(this.srcFilePath);
            this.destFileName = StringUtils.defaultIfEmpty(this.destFileName, getDestFileName());
            this.destDirPath = StringUtils.defaultIfEmpty(this.destDirPath, getDestDirPath());
            this.destFilePath = this.destDirPath + File.separator + this.destFileName;
            IConverter converter = ConverterFactory.getFactory().getConverter(srcFilePath, destFilePath);
            return new MediaConverter(converter,this);
        }

        /**
         * 验证需要转换的格式是否支持
         *
         * @param format
         * @return
         */
        private boolean checkFormatIsSupported(String format) {
            checkNotNull(format);
            List<String> supportedFormats = Splitter.on(SUPPORTED_FORMAT).splitToList(",");
            for (String supportedFormat : supportedFormats) {
                if (StringUtils.equalsIgnoreCase(supportedFormat, format)) {
                    return true;
                }
            }
            return false;
        }

        /**
         * 获取默认的目标文件名，默认与源文件同名
         * @return
         */
        private String getDestFileName() {
            String srcFileName = StringUtils.substringAfterLast(this.srcFilePath, File.separator);
            srcFileName = StringUtils.substringBeforeLast(srcFileName, ".");
            return srcFileName + "." + this.format;
        }

        /**
         * 获取默认的目标文件目录，默认与源文件同目录
         * @return
         */
        private String getDestDirPath() {
            File srcFile = new File(this.srcFilePath);
            return srcFile.getParent();
        }

    }

    /**
     * 执行多媒体转换
     * @return
     */
    public MediaInfo decode() {
        this.converter.invoke(cmdDirOnWindows,cmdDirOnLinux,timeout);
        File destFile = new File(destFilePath);
        if (!destFile.exists()) {
            LOGGER.warn("转换文件失败，请确认ffmpge是否已经安装！");
            return null;
        } else {
            MediaInfo mediaInfo = new MediaInfo(destFile);
            return mediaInfo;
        }
    }

    public static void main(String[] args) {
        MediaConverter converter = MediaConverter.builder().srcFilePath("D:\\silk2mp3\\wxid_y2prj0189ws122.silk").build();
        MediaInfo mediaInfo = converter.decode();
        System.out.println(mediaInfo.getMediaFile().getAbsolutePath());
    }
}
